#include <iostream>

#if 0
void add(int a, int b)
{
    std::cout << a + b << std::endl;    
}

void add(double a, int b)
{
    std::cout << a + b << std::endl;    
}

void add(double a, double b)
{
    std::cout << a + b << std::endl;    
}

void add(int a, double b)
{
    std::cout << a + b << std::endl;    
}

#endif

template <typename A, typename B>
void add(const A &a, const B &b)
{
    std::cout << a + b << std::endl;
}

template <typename A>
void mySwap(A &a, A &b)
{
    A temp = a;
    a = b;
    b = temp;
}

template <typename T1, typename T2, typename R>
R calculate(T1 t1, T2 t2)
{
    return (R)(t1 + t2);
}

template <typename R, typename T1, typename T2>
R calculate1(T1 t1, T2 t2)
{
    return (R)(t1 + t2);
}

int main(int argc, char const *argv[])
{
    int a = 10;
    int b = 100;
    double c = 3.14;
    double d = 9.99;

    // 显式指定类型
    add<int, int>(d, c);
    add<int, double>(10, 3.14);

    // 隐式类型推导
    add(c, d);

    int x = 10;
    int y = 20;
    mySwap(x, y);

    std::cout << "X = " << x << ", Y = " << y << "." << std::endl;

    add<int>(c, d); // 部分指定，从前向后，剩余的按昭实际参数自行推导

    // 在调用模板函数时，只能根据实参来推导形参的数据类型
    // 如果模板类型是用在返回值部分的，必须手动指定
    int res = calculate<double, double, int>(c, d);
    std::cout << "res = " << res << std::endl;

    res = calculate1<int>(c, d);
    std::cout << "res = " << res << std::endl;

    return 0;
}
